package Sds

import "math"

type ISds interface {
	GetLen() uint64
	SetValue(bts []byte) ISds
	GetValues() []byte
	GetFree() uint64
}

const (
	MaxType5  = 1 << 5
	MaxType8  = math.MaxUint8
	MaxType16 = math.MaxUint16
	MaxType32 = math.MaxUint32
	MaxType64 = math.MaxInt64
)

func ReqType(size uint64) uint64 {
	if size < MaxType5 {
		return MaxType5
	}
	if size < MaxType8 {
		return MaxType8
	}
	if size < MaxType16 {
		return MaxType16
	}
	if size < MaxType32 {
		return MaxType32
	}
	return MaxType64
}

func NewSds(bts []byte) ISds {
	l := ReqType(uint64(len(bts)))
	var sds ISds
	switch l {
	case MaxType5:
		sds = &Str5{
			flags: 0,
			char:  make([]byte, MaxType5, MaxType5),
		}
	case MaxType8:
		sds = &Str8{
			flags: 0,
			char:  make([]byte, MaxType8, MaxType8),
			len:   MaxType8,
			free:  MaxType8,
		}
	case MaxType16:
		sds = &Str16{
			flags: 0,
			char:  make([]byte, MaxType16, MaxType16),
			len:   MaxType16,
			free:  MaxType16,
		}
	case MaxType32:
		sds = &Str32{
			flags: 0,
			char:  make([]byte, MaxType32, MaxType32),
			len:   MaxType32,
			free:  MaxType32,
		}
	case MaxType64:
		sds = &Str64{
			flags: 0,
			char:  make([]byte, MaxType64, MaxType64), // too Large in go math.MaxUint64
			len:   MaxType64,
			free:  MaxType64,
		}
	}
	if sds != nil {
		sds.SetValue(bts)
	}
	return nil
}

type Str5 struct {
	flags uint8
	char  []byte
}

type Str16 struct {
	flags uint8
	char  []byte
	len   uint16
	free  uint16
}

type Str8 struct {
	flags uint8
	char  []byte
	len   uint8
	free  uint8
}

type Str32 struct {
	flags uint8
	char  []byte
	len   uint32
	free  uint32
}

type Str64 struct {
	flags uint8
	char  []byte
	len   uint64
	free  uint64
}
